package cn.edu.gdut.deepcode.component;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static cn.edu.gdut.deepcode.utils.CommonUtils.OBJECT_MAPPER;


@Component
@RequiredArgsConstructor
@Slf4j
public class CacheComponent {
    @Autowired
    private final StringRedisTemplate redisTemplate;

    public StringRedisTemplate getRedisTemplate(){
        return redisTemplate;
    }

    /**
     *
     * @param key 分享码的键
     * @return 0表示过期,-1表示永久,其他表示未过期
     */
    public Long sharedCodeExpired(String key) {
        // 获取缓存
        String value = redisTemplate.opsForValue().get(key);
        if (StrUtil.isBlank(value)) {
            // 已过期
            return 0L;
        }
        Long expire = redisTemplate.getExpire(key);
        if (
                expire == null ||
                        expire == -2L
        ) {
            // 已过期
            return 0L;
        }
        expire= redisTemplate.getExpire(key);
        return  expire==null||expire==-2L?0L:expire;
    }
    public void appendListToListCache(List<?> list, String key, long expire, TimeUnit unit){
        if (CollUtil.isEmpty(list)){
            log.warn("list数据为空->{}",list);
            return;
        }
        try {
            List<String> jsons=new ArrayList<>(list.size());
            for (Object o : list) {
                jsons.add(OBJECT_MAPPER.writeValueAsString(o));
            }
            redisTemplate.opsForList().rightPushAll(key,jsons);
            setExpire(key, expire, unit);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
    public Long getListCacheSize(String key){
        Long size = redisTemplate.opsForList().size(key);
        if(size == null){
            size=0L;
            log.warn("key不存在,key->{}",key);
        }
        return size;
    }
    public <R> List<R> getListCache(Class<R> clazz, String key, Long start, Long end) throws JsonProcessingException {
        List<String> result;
        Long size = getListCacheSize(key);
        if (size==0||start>=size){
            result=null;
        }else {
            if (end>=size){
                end=size-1;
            }
            result=redisTemplate.opsForList().range(key, start, end);
        }
        if (result==null){
//            log.warn("缓存数据为空,key->{},range->({},{}),size->{}",key,start,end,size);
            return Collections.emptyList();
        }else{
            List<R> temp=new ArrayList<>(result.size());
            for (String json : result) {
                temp.add(OBJECT_MAPPER.readValue(json,clazz));
            }
            return temp;
        }
    }

    public void setValueCache(String key,String value,Long expire,TimeUnit timeUnit){
        redisTemplate.opsForValue().set(key,value,expire,timeUnit);
    }

    public String getValueCache(String key){
        String value = redisTemplate.opsForValue().get(key);
        if (StrUtil.isEmpty(value)){
            log.warn("缓存value数据异常,key->{},value->{}",key,value);
//            value="0";
        }
        return value;
    }

    public Long incrementValueCache(String key){
        return redisTemplate.opsForValue().increment(key);
    }

    public Long decrementValueCache(String key){
        Long value = redisTemplate.opsForValue().decrement(key);
        if (value==null||value<0){
            log.warn("value值异常,value->{}",value);
        }
        return value;
    }

    public void putMapToHashCache(Map<?,?> source, String key, Long expire, TimeUnit timeUnit){
        if(MapUtil.isEmpty(source)){
            log.warn("source状态异常,source->{}",source);
            return;
        }
        redisTemplate.opsForHash().putAll(key,source);
        setExpire(key, expire, timeUnit);
    }

    public boolean setExpire(String key, Long expire, TimeUnit timeUnit) {
        return Boolean.TRUE.equals(redisTemplate.expire(key, expire, timeUnit));
    }

    public Map<Object,Object> getHashCache(String key){
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);
        if (MapUtil.isEmpty(entries)){
            log.warn("缓存数据异常,key->{},entries->{}",key,entries);
            entries= Collections.emptyMap();
        }
        return entries;
    }

    public void updateEntryInHashCache(String key,String hashKey,String value){
        redisTemplate.opsForHash().put(key,hashKey,value);
    }

}
